home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb / sprite / ptraceMips.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-03  |  10.0 KB  |  373 lines

  1. /*
  2.  * ptrace.c --
  3.  *
  4.  *    Routines for creating a Unix like debugger interface to Sprite.
  5.  *
  6.  * Copyright 1991 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that this copyright
  10.  * notice appears in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  * $Header: /sprite/src/kernel/mach/spur.md/RCS/machConfig.c,v 1.2 88/11/11 15:3
  16. 6:43 mendel Exp $ SPRITE (Berkeley)
  17.  */
  18.  
  19. #include <stdio.h> 
  20. #include "sprite.h"
  21. #include "status.h"
  22. #include <sys/types.h>
  23. #include "sys/ptrace.h"
  24. #include <errno.h>
  25. #include <proc.h>
  26. #include <signal.h>
  27. #include <sys/wait.h>
  28.  
  29. static int mapStatusToErrno();
  30.  
  31. /* 
  32.  *----------------------------------------------------------------------
  33.  *
  34.  * ptrace --
  35.  *
  36.  *    Emulate Unix ptrace system call.
  37.  *
  38.  * Results:
  39.  *    An integer.
  40.  *
  41.  * Side effects:
  42.  *
  43.  *----------------------------------------------------------------------
  44.  */
  45.  
  46. int
  47. ptrace (request,pid,addr,data, addr2)
  48.      int request;    /* Data
  49.      int pid;            /* Process id of debugee. */
  50.      char *addr;        
  51.      int data;
  52.      char *addr2;
  53. {
  54.      extern int    errno;
  55.      Proc_DebugState process_state;
  56.      int    returnData;
  57.      ReturnStatus    status;
  58.  
  59.  
  60. #if 0
  61.      printf("ptrace: request %d, id 0x%x, addr 0x%x, data 0x%x\n", 
  62.      request, pid, addr);
  63. #endif
  64.      errno = 0;
  65.      if ((int) addr < 0) {
  66.      printf("Negative addr\n");
  67.      }
  68.      switch (request) {
  69.         case PT_TRACE_ME: {      /* 0, by tracee to begin tracing */
  70.          extern int    _execDebug;
  71.          /*
  72.           * This is a hack to emulate the ptrace(0) request.  ptrace(0) 
  73.           * seems to cause the exec() to stop after the first instruction.
  74.           * Setting _execDebug to true causes the Proc_Exec call to
  75.           * enter the debug queue after the first instruction.
  76.           */
  77.           _execDebug = 1;
  78.           return 0;
  79.     }
  80.         case PT_READ_I:    /* 1, read word from text segment */
  81.         case PT_READ_D:  { /* 2, read word from data segment */
  82.         status = Proc_Debug(pid,PROC_READ, sizeof(int),addr,
  83.                 &returnData);
  84.         errno = mapStatusToErrno(status);
  85.         return errno ? -1 : returnData; 
  86.         }
  87.         case PT_WRITE_I:    /* 4, write word into text segment */
  88.         case PT_WRITE_D: {  /* 5, write word into data segment */
  89.         status = Proc_Debug(pid,PROC_WRITE, sizeof(int),&data,addr);
  90.         if (status != 0) {
  91.         fprintf(stderr,
  92.             "Proc_Debug failed status = %x, pid = %x, addr = %x\n",
  93.             status, pid, addr);
  94.         }
  95.  
  96.         errno = mapStatusToErrno(status);
  97.         return errno ? -1 : data; 
  98.         }
  99.         case PT_CONTINUE: {       /* 7, continue process */
  100.         if (data != 0 && data != 1) {
  101.         if (kill(pid,data) != 0) {
  102.             perror("kill");
  103.             return -1;
  104.         }
  105.         }
  106.         status = Proc_Debug(pid,PROC_CONTINUE,0,0,0);
  107.         errno = mapStatusToErrno(status);
  108.         return errno ? -1 : 0; 
  109.         }
  110.         case PT_KILL: {      /* 8, terminate process */
  111.         if (kill(pid,SIGKILL) != 0) {
  112.         perror("kill");
  113.         return -1;
  114.         }
  115.         status= Proc_Debug(pid,PROC_DETACH_DEBUGGER,0,0,0);
  116.         (void) kill(pid,SIGKILL); /* Sometimes Sprite takes more than
  117.                        * one kill.
  118.                        */
  119.         (void) kill(pid,SIGCONT); 
  120.         status= Proc_Debug(pid,PROC_DETACH_DEBUGGER,0,0,0);
  121.         (void) kill(pid,SIGKILL); /* Sometimes Sprite takes more than
  122.                        * one kill.
  123.                        */
  124.         (void) kill(pid,SIGCONT); 
  125.         (void) kill(pid,SIGKILL); /* Sometimes Sprite takes more than
  126.                        * one kill.
  127.                        */
  128.         status= Proc_Debug(pid,PROC_DETACH_DEBUGGER,0,0,0);
  129.         if (status == PROC_INVALID_PID) {
  130.         status = SUCCESS;
  131.         }
  132.         errno = mapStatusToErrno(status);
  133.         return errno ? -1 : 0; 
  134.     }
  135.         case PT_STEP:{ /* 9, single step process */
  136.         status = Proc_Debug(pid,PROC_SINGLE_STEP,0,0,0);
  137.         errno = mapStatusToErrno(status);
  138.         return errno ? -1 : 0; 
  139.         }
  140.         case PT_ATTACH: {  /* 10, attach to an existing process */
  141.         status = Proc_Debug(pid,PROC_GET_THIS_DEBUG,0,0,0);
  142.         errno = mapStatusToErrno(status);
  143.         return errno ? -1 : 0; 
  144.     }
  145.         case PT_DETACH: {  /* 11, detach from a process */
  146.         if (data != 0 && data != 1) {
  147.         if (kill(pid,data) != 0) {
  148.             perror("kill");
  149.             return -1;
  150.         }
  151.         }
  152.         status = Proc_Debug(pid,PROC_DETACH_DEBUGGER,0,0,0);
  153.         errno = mapStatusToErrno(status);
  154.         return errno ? -1 : 0; 
  155.     }
  156.        case PT_READ_U: {   /* 3, read word from user struct */
  157.         Mach_RegState    *regPtr;
  158.         int            reg;
  159.         reg = (int) addr;
  160.         if ((reg >= 0) && (reg <  NPTRC_REGS)) {
  161.         status = Proc_Debug(pid,PROC_GET_DBG_STATE,0,0,&process_state);
  162.         errno = mapStatusToErrno(status);
  163.         if (errno) {
  164.             return -1;
  165.         }
  166.         regPtr = &process_state.regState;
  167.         if (reg < FPR_BASE) {
  168.             returnData = regPtr->regs[reg];
  169.         } else if (reg < FPR_BASE + NFP_REGS) {
  170.             returnData = regPtr->fpRegs[reg - FPR_BASE];
  171.         } else if (reg == PC) {
  172.             returnData = (int) regPtr->pc;
  173.         } else if (reg == MMHI) {
  174.             returnData = regPtr->mfhi;
  175.         } else if (reg == MMLO) {
  176.             returnData = regPtr->mflo;
  177.         } else if (reg == FPC_CSR) {
  178.             returnData = regPtr->fpStatusReg;
  179.         } else {
  180.             returnData = -1;
  181.         }
  182.         return returnData;
  183.         } else {
  184.         return -1;
  185.         }
  186.     }
  187.        case PT_WRITE_U: {   /* 6, write word into user struct */
  188.         Mach_RegState    *regPtr;
  189.         int            reg;
  190.         reg = (int) addr;
  191.         if ((reg >= 0) && (reg <  NPTRC_REGS)) {
  192.         status = Proc_Debug(pid,PROC_GET_DBG_STATE,0,0,&process_state);
  193.         errno = mapStatusToErrno(status);
  194.         if (errno) {
  195.             return -1;
  196.         }
  197.         regPtr = &process_state.regState;
  198.         if (reg < FPR_BASE) {
  199.             regPtr->regs[reg] = data;
  200.         } else if (reg < FPR_BASE + NFP_REGS) {
  201.             regPtr->fpRegs[reg - FPR_BASE] = data;
  202.         } else if (reg == PC) {
  203.             regPtr->pc = (Address) data;
  204.         } else if (reg == MMHI) {
  205.             regPtr->mfhi = data;
  206.         } else if (reg == MMLO) {
  207.             regPtr->mflo = data;
  208.         } else if (reg == FPC_CSR) {
  209.             regPtr->fpStatusReg = data;
  210.         } else {
  211.             return -1;
  212.         }
  213.         status = Proc_Debug(pid,PROC_SET_DBG_STATE,0,&process_state,0);
  214.         } else {
  215.         return -1;
  216.         }
  217.     }
  218.        default: {
  219.         return -1;
  220.     }
  221.     }
  222. }
  223.  
  224. /* 
  225.  *----------------------------------------------------------------------
  226.  *
  227.  * wait --
  228.  *
  229.  *    Emulate the Unix wait system call when used to wait for a 
  230.  *    process being ptraced.
  231.  *
  232.  * Results:
  233.  *    An integer.
  234.  *
  235.  * Side effects:
  236.  *
  237.  *----------------------------------------------------------------------
  238.  */
  239. int
  240. wait (statusPtr)
  241.     union wait *statusPtr;
  242. {
  243.     ReturnStatus    status;
  244.     Proc_DebugState process_state;
  245.     extern int inferior_pid;
  246.  
  247.     if (!inferior_pid) {
  248.     error("Trying to wait for nonexistant process");
  249.     }
  250.     /*
  251.      * Wait for this process to enter the debug list.
  252.      */
  253.     status = Proc_Debug(inferior_pid,PROC_GET_THIS_DEBUG,0,0,0);
  254.     if (status == SUCCESS) {
  255.     if (statusPtr == (union wait *) 0) {
  256.         goto reapChild;
  257.     }
  258.     status = Proc_Debug(inferior_pid,PROC_GET_DBG_STATE,0,0,&process_state);
  259.     if (status == SUCCESS) {
  260.         int unixSignal;
  261.             statusPtr->w_status = 0;
  262.             statusPtr->w_stopval = WSTOPPED;
  263.             if (process_state.termReason == PROC_TERM_SUSPENDED) {
  264.                 (void)Compat_SpriteSignalToUnix(process_state.termStatus,
  265.                            &unixSignal);
  266.                 statusPtr->w_stopsig = unixSignal;
  267.         if (process_state.termStatus == SIG_DEBUG ||
  268.             process_state.termStatus == SIG_TRACE_TRAP ||
  269.             process_state.termStatus == SIG_BREAKPOINT) {
  270.             statusPtr->w_stopsig = SIGTRAP;
  271.         }
  272.             } else if (process_state.termReason == PROC_TERM_SIGNALED ||
  273.                        process_state.termReason == PROC_TERM_RESUMED) {
  274.                 (void)Compat_SpriteSignalToUnix(process_state.termStatus, 
  275.                         &unixSignal);
  276.                 statusPtr->w_stopsig = unixSignal;
  277.         if (process_state.termStatus == SIG_DEBUG ||
  278.             process_state.termStatus == SIG_TRACE_TRAP ||
  279.             process_state.termStatus == SIG_BREAKPOINT) {
  280.             statusPtr->w_stopsig = SIGTRAP;
  281.         }
  282.             } else {
  283.         statusPtr->w_status = 0;
  284.                 statusPtr->w_retcode = process_state.termStatus;
  285.         (void) ptrace(PT_DETACH,inferior_pid,0,SIGKILL,0);
  286.             }
  287.         return inferior_pid;
  288.     }
  289.     }
  290. reapChild:
  291.     { 
  292.         Proc_PID    pid;
  293.     int        reason, childStatus, subStatus;
  294.     status = Proc_Wait(1, (int *) &inferior_pid, PROC_WAIT_BLOCK, 
  295.         &pid, &reason,  &childStatus, &subStatus, 
  296.         (Proc_ResUsage *) NULL);
  297.         if (statusPtr != NULL)  {
  298.         int        unixSignal;
  299.             statusPtr->w_status = 0;
  300.             if (reason == PROC_TERM_SUSPENDED) {
  301.                 (void)Compat_SpriteSignalToUnix(childStatus, &unixSignal);
  302.                 statusPtr->w_stopval = WSTOPPED;
  303.                 statusPtr->w_stopsig = unixSignal;
  304.             } else if (reason == PROC_TERM_SIGNALED ||
  305.                        reason == PROC_TERM_RESUMED) {
  306.                 (void)Compat_SpriteSignalToUnix(childStatus, &unixSignal);
  307.                 statusPtr->w_stopval = WSTOPPED;
  308.                 statusPtr->w_termsig = unixSignal;
  309.             } else {
  310.                 statusPtr->w_retcode = childStatus;
  311.         (void) ptrace(PT_DETACH,inferior_pid,0,SIGKILL,0);
  312.             }
  313.         }
  314.     }
  315.     return inferior_pid;
  316. }
  317.  
  318.  
  319.  
  320.  
  321. /* 
  322.  *----------------------------------------------------------------------
  323.  *
  324.  * mapStatusToErrno --
  325.  *
  326.  *    Map a Sprite status return code to a Unix errno. This is intended 
  327.  *    to work only on the status codes returns from Proc_Debug.
  328.  *
  329.  * Results:
  330.  *    An integer.
  331.  *
  332.  * Side effects:
  333.  *      None
  334.  *
  335.  *----------------------------------------------------------------------
  336.  */
  337.  
  338. static int
  339. mapStatusToErrno(status)
  340.     ReturnStatus    status;
  341. {
  342.     int    returnValue;
  343.  
  344.     if (status == SUCCESS) {
  345.     return 0;
  346.     }
  347.  
  348.     switch (status) {
  349.  
  350.     case PROC_INVALID_PID:
  351.     returnValue = ESRCH;
  352.     break;
  353.  
  354.     case SYS_INVALID_ARG:
  355.     returnValue = EINVAL;
  356.     break;
  357.  
  358.     case SYS_ARG_NOACCESS:
  359.     returnValue = EINVAL;
  360.     break;
  361.  
  362.     case GEN_ABORTED_BY_SIGNAL:
  363.     returnValue = EINTR;
  364.     break;
  365.  
  366.     default:
  367.     returnValue = EIO;
  368.     break;
  369.     }
  370.     return returnValue;
  371. }
  372.  
  373.